#include <mono/jit/jit.h>
#include <mono/metadata/object.h>
#include <mono/metadata/environment.h>
#include <mono/metadata/assembly.h>
#include <mono/metadata/debug-helpers.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>

static void bm_sharp2native(MonoDomain *domain, const char *file);

int main(int argc, char* argv[]) {
  MonoDomain *domain;

  if (argc != 2) {
    printf("%s <csharp.dll>\n", argv[0]);
    return 1;
  }

  domain = mono_jit_init_version("benchmark", "v4.0");
  bm_sharp2native(domain, argv[1]);
  mono_jit_cleanup(domain);

  return 0;
}

static void bm_sharp2native(MonoDomain *domain, const char* file) {
  /* 1. find a class
   * 2. just call a static function
   * 3. done
   */
  MonoAssembly *assembly;
  MonoImage *image;
  MonoClass *mclass;
  MonoMethodDesc *method_desc;
  MonoMethod *method;
  MonoObject *exception;

  assembly = mono_domain_assembly_open(domain, file);
  assert(assembly);
  image = mono_assembly_get_image(assembly);
  assert(image);
  mclass = mono_class_from_name(image, "BenchMark", "Entry");
  assert(mclass);
  method_desc = mono_method_desc_new(":Sharp2Native", 0);
  assert(method_desc);
  method = mono_method_desc_search_in_class(method_desc, mclass);
  assert(method);

  mono_runtime_invoke(method, NULL, NULL, &exception);
  if (exception) {
    printf("%s: exception\n", __func__);
  }

  mono_method_desc_free(method_desc);
}
